
/**
 *  @file
 *  @brief   单元集中力计算
 *  @author  wanghuan
 *  @date    2024.10.23
 *  @version  v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include "Utility/Algebra/Matrix.h"
#include "Utility/Algebra/sgEigenSpace.h"
#include "DataStructure/Common/Status.h"
#include "DataStructure/Common/Out.h"
#include "DataStructure/Common/Id.h"
#include "DataStructure/Common/Real.h"

#include "DataStructure/Input/Load/FORCEData.h"
#include "DataStructure/Input/Load/PLOADData.h"
#include "DataStructure/Input/Load/PLOAD1Data.h"
#include "DataStructure/Input/Load/PLOAD2Data.h"
#include "DataStructure/Input/Load/PLOAD4Data.h"
#include "DataStructure/Input/Load/DAREAData.h"
#include "DataStructure/Input/Node/NodeData.h"
#include "DataStructure/Input/Element/CBARData.h"
#include "DataStructure/Input/Element/CBEAMData.h"

#include "DBManager/IService/Input/Node/INodeService.h"
#include "SGFem/Pre/Assembly/Assembly.h"
#include "SGFem/Pre/Assembly/CoordinateProcessor.h"
#include "TaskExport.h"

/** @brief 集中力载荷计算
 *
 */
class Task_DECLSPEC LoadCalculator
{
public:
    /** @brief 计算Force/Moment 在位移输出坐标系下载荷分量
     *
     * @param[in] coordHandler 提供坐标系信息
     * @param[in] force        载荷定义
     * @param[in] node         载荷作用点
     * @param[out] loadMatrix  等价载荷向量
     */
    static void ForceCalc (const SG::FEMSolver::CoordinateProcessor& coordHandler,
                           const SG::DataStructure::FEM::FORCEData&  force,
                           const SG::DataStructure::FEM::NodeData&   node,
                           SG::Algebra::Matrix& _OUT                 loadMatrix);

    /** @brief 计算PLOAD 在位移输出坐标系下载荷分量
     *
     * @param[in]  nodeService  提供节点信息
     * @param[in]  pLoad        均布载荷
     * @param[out] loadMatrix   等效节点载荷向量
     */
    static void PLoadCalc (const std::shared_ptr<SG::DBManager::INodeService>& nodeService,
                           const SG::DataStructure::FEM::PLOADData&            pLoad,
                           SG::Algebra::Matrix& _OUT                           loadMatrix);

     /** @brief 计算PLOAD1【作用在三角形或者四边形节点上均布压力】 在位移输出坐标系下载荷分量
     *
     * @param[in]  pLoad1        载荷均布载荷
     * @param[out] loadMatrix   等价载荷向量
     */
    static void PLoad1Calc (const SG::DBManager::DBServiceFactorySP             dbServiceFactory,
                            const SG::DataStructure::FEM::PLOAD1Data&           pLoad1,
                            SG::Algebra::Matrix& _OUT                           loadMatrix,
                            std::vector<std::size_t>& _OUT                      nodeIndexes);
                            
    /** @brief 计算PLOAD2 在位移输出坐标系下载荷分量
     *
     * @param[in]  dbServiceFactory  提供节点信息
     * @param[in]  pLoad2        载荷均布载荷
     * @param[out] loadMatrix   等价载荷向量
     * @param[out] nodeIndexes  载荷作用节点对应的位移输出坐标系
     */
    static void PLoad2Calc (const SG::DBManager::DBServiceFactorySP             dbServiceFactory,
                            const SG::DataStructure::FEM::PLOAD2Data&           pLoad2,
                            SG::Algebra::Matrix& _OUT                           loadMatrix,
                            std::vector<std::size_t>& _OUT                      nodeIndexes);

    /** @brief 计算PLOAD4[双线性分布] 在位移输出坐标系下载荷分量
     *
     * @param[in]  coordHandler 提供坐标系信息
     * @param[in]  nodeService  提供节点信息
     * @param[in]  pLoad4       载荷均布载荷
     * @param[out] loadMatrix   等价载荷向量
     */
    static SG::DataStructure::Common::Status PLoad4Calc (const SG::DBManager::DBServiceFactorySP&  dbServiceFactory,
                                                         const SG::DataStructure::FEM::PLOAD4Data& pLoad4,
                                                         SG::Algebra::Matrix& _OUT                 loadMatrix,
                                                         std::vector<std::size_t>& _OUT            nodeIndexes);

    /**
     * @brief    计算重力载荷
     *
     * @param    dbServiceFactory
     * @param    loadCaseIds     载荷工况Id
     */
    static void GravityLoadCalc (const SG::DBManager::DBServiceFactorySP&       dbServiceFactory,
                                 const std::set<SG::DataStructure::Common::Id>& loadCaseIds);

    /** @brief 计算所有工况下的静力载荷 */
    static void ComputeStaticLoad (const SG::DBManager::DBServiceFactorySP dbServiceFactory, const std::set<SG::DataStructure::Common::Id>& loadCaseIds);


    static void calcDAREAForce (const std::vector<SG::DataStructure::FEM::DAREAData>& dareaSet, SG::Algebra::Vec_t& _OUT force);
};


